package hs.framework.opcClient.controller;

import hs.framework.opcClient.entity.OPCConfig;
import hs.framework.opcClient.entity.OPCServer;
import hs.framework.opcClient.service.impl.OPCService;
import hs.framework.opcClient.utils.*;
import org.openscada.opc.lib.da.Server;
import org.jinterop.dcom.common.JIException;
import org.jinterop.dcom.core.JIVariant;
import org.openscada.opc.lib.common.AlreadyConnectedException;
import org.openscada.opc.lib.common.NotConnectedException;
import org.openscada.opc.lib.da.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.net.UnknownHostException;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

@CrossOrigin
@RestController
@RequestMapping("/opc")
public class OPCController {

    @Autowired
    OPCConfig opcConfig;
    private static Logger log = LoggerFactory.getLogger(OPCController.class);

    @GetMapping("getServer")
    public List<ServerInfo> getServer() throws Throwable {
        return OPCService.getServers();
    }

    @GetMapping("items")
    public List<String> getAll() throws AlreadyConnectedException, JIException, UnknownHostException {
        Server server = OPCService.openServer();
        try {
            OPCService opcService = new OPCService();
            opcService.hello();
            Collection<String> itemIds = server.getFlatBrowser().browse();
            List<String> result = itemIds.parallelStream().collect(Collectors.toList());
            return result;
        } catch (final JIException e) {
            OPCService.disposeServer();
            log.error(e.getMessage());
            log.error(String.format("%08X: %s", e.getErrorCode(), server.getErrorMessage(e.getErrorCode())));
        } catch (UnknownHostException e) {
            e.printStackTrace();
            log.error(e.getMessage());
        }
        return null;
    }

    @GetMapping("dataitem")
    public DataItem getDataItemsFromServer(String itemId) throws AlreadyConnectedException, JIException, UnknownHostException {
        final Server server = OPCService.openServer();
        DataItem dataItem = Browser.readSync(server,itemId);
        return dataItem;
    }

    @GetMapping("dataitems")
    public List<DataItem> getDataItemsFromServer() throws AlreadyConnectedException, JIException, UnknownHostException {
        final Server server = OPCService.openServer();
        List<DataItem> dataItems = Browser.readSync(server);
        return dataItems;
    }

    @PutMapping("write")
    public DataItem changOpcBool(@RequestBody DataItem dataItem) throws AlreadyConnectedException, JIException, UnknownHostException, NotConnectedException, DuplicateGroupException {
        final Server server = OPCService.openServer();
        final Group group = server.addGroup("write");
        try {
            // Add a new item to the group，
            // 将一个item加入到组，item名字就是MatrikonOPC Server或者KEPServer上面建的项的名字比如：u.u.TAG1，PLC.S7-300.TAG1
            final Item item = group.addItem(dataItem.getItemId());
            //根据type做数据转型处理
//            final JIVariant value = new JIVariant((boolean)dataItem.getValue());
            Object o = dataItem.getValue();
            o = TypeChangeUtil.change(o,Class.forName(dataItem.getDataType()));
            final JIVariant value = JIVariant.makeVariant(o,true);
            int result = item.write(value);
            DataItem res = JiVariantUtil.parseValue(item.getId(),item.read(false));

            return res;
        } catch (final JIException e) {
            log.error(e.getMessage());
            log.error(String.format("%08X: %s", e.getErrorCode(), server.getErrorMessage(e.getErrorCode())));
        } catch (AlreadyConnectedException e) {
            e.printStackTrace();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (AddFailedException e) {
            e.printStackTrace();
        } catch (NotConnectedException e) {
            e.printStackTrace();
        } catch (DuplicateGroupException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            server.removeGroup(group,true);
        }
        return null;

    }
}
